package com.hc.likelistenmusic.activity

import android.annotation.SuppressLint
import android.app.Dialog
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.telephony.TelephonyManager
import android.view.WindowManager
import android.widget.EditText
import android.widget.RemoteViews
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import androidx.viewpager2.widget.ViewPager2.ORIENTATION_HORIZONTAL
import androidx.viewpager2.widget.ViewPager2.OVER_SCROLL_NEVER
import com.hc.likelistenmusic.R
import com.hc.likelistenmusic.bean.LocalMusic
import com.hc.likelistenmusic.config.NotificationPlayStatus
import com.hc.likelistenmusic.fragment.LazyFragment
import com.hc.likelistenmusic.fragment.LocalLrcFragment
import com.hc.likelistenmusic.fragment.LocalMusicFragment
import com.hc.likelistenmusic.presenter.LocalMusicPresenter
import com.hc.likelistenmusic.receiver.NotificationClickJumpTopActivityReceiver
import com.hc.likelistenmusic.util.ScreenUtil
import com.hc.likelistenmusic.view.CommonDialog
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer

class LocalMusicActivity : AppCompatActivity() {
    val TAG = "HUACHEN_LocalMusicActivity"
    lateinit var mVp_alm: ViewPager2
    lateinit var mVp_alm_adapter: FragmentStateAdapter
    lateinit var mLocalMusicPresenter: LocalMusicPresenter
    lateinit var mComeInPhoneReceiver: ComeInPhoneReceiver
    var mNotificationManager: NotificationManager? = null
    lateinit var mBackDialog: CommonDialog
    lateinit var mScaningDialog: CommonDialog
    var mRemoteView: RemoteViews? = null
    var mVp_alm_adapter_fragments: MutableList<LazyFragment>
    var mNotificationActionReceiver: NotificationActionReceiver? = null
    var mNotification: Notification? = null
    var mIsRingLing = false
    var mExitTime = -1L
    val mNotificationId = 1

    init {
        mVp_alm_adapter_fragments = mutableListOf()
        mVp_alm_adapter_fragments.add(LocalMusicFragment())
        mVp_alm_adapter_fragments.add(LocalLrcFragment())
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val window = window
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
        window.statusBarColor = resources.getColor(R.color.color_theme)
        window.navigationBarColor = resources.getColor(R.color.color_theme)
        setContentView(R.layout.activity_local_music)

        mLocalMusicPresenter = LocalMusicPresenter(this)
        initViews()
        registerComeInPhoneReceiver()
        generateNotification()
    }

    override fun onResume() {
        super.onResume()
        if (mIsRingLing) {
            onPausePlay()
        } else {
            if (!mBackDialog.isShowing) {
                onResumePlay()
            }
        }
    }

    override fun onStop() {
        super.onStop()
        if (mIsRingLing) {
            onPausePlay()
        } else {
            if (!mBackDialog.isShowing) {
                onResumePlay()
            }
        }
        ScreenUtil.hideSoftInput(this, findMusicFragment().mEt_fm_filter_musics)
    }

    override fun onDestroy() {
        super.onDestroy()
        findMusicFragment().mLoadLocalMusicJob?.cancel()
        findLrcFragment().mLoadLocalLrcJob?.cancel()
        mNotification?.apply {
            mNotificationManager?.cancel(mNotificationId)
        }
        unregisterReceiver(mComeInPhoneReceiver)
        mNotificationActionReceiver?.let {
            unregisterReceiver(mNotificationActionReceiver)
        }
        mLocalMusicPresenter.onDestroy()
    }

    override fun onBackPressed() {
        if (mVp_alm.currentItem != 0) {
            mVp_alm.currentItem = 0
        } else {
            if (mExitTime == -1L) {
                mExitTime = System.currentTimeMillis()
                showToast(mLocalMusicPresenter.getExitInfo())
            } else {
                val currentTimeMillis = System.currentTimeMillis()
                if (currentTimeMillis - mExitTime < 2000) {
                    finish()
                } else {
                    mExitTime = currentTimeMillis
                    showToast(mLocalMusicPresenter.getExitInfo())
                }
            }
        }
    }

    private fun registerNotificationActionReceiver() {
        mNotificationActionReceiver = NotificationActionReceiver()
        IntentFilter().apply {
            addAction(NotificationPlayStatus.STATUS_PREV)
            addAction(NotificationPlayStatus.STATUS_PLAY_OR_PAUSE)
            addAction(NotificationPlayStatus.STATUS_NEXT)
            addAction(NotificationPlayStatus.STATUS_CLOSE)
            registerReceiver(mNotificationActionReceiver, this)
        }
    }

    @SuppressLint("LaunchActivityFromNotification")
    private fun generateNotification() {
        if (!ensureNotificationPermission()) {
            return
        }
        mNotificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
        registerNotificationActionReceiver()
        generateRemoteViews()
        var channelId = "Notification_Play_Control"
        var channelName = "通知栏播放控制"
        var importance = NotificationManagerCompat.IMPORTANCE_HIGH
        generateNotificationChannel(channelId, channelName, importance)
        val pendingIntent = PendingIntent.getBroadcast(
            applicationContext, 0, Intent(
                applicationContext,
                NotificationClickJumpTopActivityReceiver::class.java
            ), PendingIntent.FLAG_UPDATE_CURRENT
        )
        mNotification = NotificationCompat.Builder(this, channelId).apply {
            setContentIntent(pendingIntent)
            setWhen(System.currentTimeMillis())
            setSmallIcon(R.drawable.app_logo)
            setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.app_logo))
            setCustomContentView(mRemoteView)
            setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
            setAutoCancel(false)
            setOnlyAlertOnce(true)
            setOngoing(true)
        }.let {
            it.build()
        }
    }

    private fun showNotification() {
        mNotification?.apply {
            mNotificationManager?.notify(mNotificationId, this)
        }
    }

    fun updateNotification(show: Boolean) {
        if (show) {
            mRemoteView?.setImageViewResource(R.id.iv_npc_playorpause, R.drawable.img_pause)
            mRemoteView?.setTextColor(R.id.tv_npc_songinfo, Color.GREEN)
        } else {
            mRemoteView?.setImageViewResource(R.id.iv_npc_playorpause, R.drawable.img_play)
            mRemoteView?.setTextColor(R.id.tv_npc_songinfo, Color.RED)
        }
        val musicFragment = findMusicFragment()
        val currentMusic = musicFragment.mLocalMusicList[musicFragment.mCurrentItemSelectedPosition]
        mRemoteView?.setTextViewText(
            R.id.tv_npc_songinfo,
            "${currentMusic.name} - ${currentMusic.singer}"
        )
        mNotificationManager?.notify(mNotificationId, mNotification)
    }

    private fun dismissNotification() {
        findMusicFragment().onSearchOrNotificationClick(false)
        mNotificationManager?.cancel(mNotificationId)
    }

    private fun ensureNotificationPermission(): Boolean {
        return NotificationManagerCompat.from(this).areNotificationsEnabled()
    }

    private fun generateNotificationChannel(
        channelId: String,
        channelName: String,
        importance: Int
    ) {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
            NotificationChannel(channelId, channelName, importance).apply {
                enableLights(false)
                enableVibration(false)
                vibrationPattern = LongArray(0) { 0 }
                setSound(null, null)
                mNotificationManager?.createNotificationChannel(this)
            }
        }
    }

    private fun onPausePlay() {
        val musicFragment = findMusicFragment()
        val lrcFragment = findLrcFragment()
        if (musicFragment.mCurrentItemSelectedPosition != -1 && (isPlaying())) {
            pause()
            cancelProgress()
            musicFragment.resumeOrPauseRotate(true)
            lrcFragment.mLv_fl.pauseAutoScroll()
            updateNotification(false)
        }
    }

    fun cancelProgress() {
        mLocalMusicPresenter.cancelProgress()
    }

    private fun onResumePlay() {
        val musicFragment = findMusicFragment()
        val lrcFragment = findLrcFragment()
        if (musicFragment.mIsHandControl) {
            return
        }
        if (musicFragment.mCurrentItemSelectedPosition != -1 && (!isPlaying())) {
            try {
                play()
                mLocalMusicPresenter.sendProgress()
                musicFragment.resumeOrPauseRotate(false)
                lrcFragment.mLv_fl.resumeAutoScroll()
                updateNotification(true)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

    fun findMusicFragment(): LocalMusicFragment {
        return mVp_alm_adapter_fragments.get(0) as LocalMusicFragment
    }

    private fun findLrcFragment(): LocalLrcFragment {
        return mVp_alm_adapter_fragments.get(1) as LocalLrcFragment
    }

    fun onPlayModeChangedFromMf(mode: Int) {
        findLrcFragment().onPlayModeChanged(mode)
    }

    fun getSearchEditText(): EditText {
        return findMusicFragment().mEt_fm_filter_musics
    }

    fun onPlayModeChangedFromLf() {
        findMusicFragment().onPlayModeClick()
    }

    private fun registerComeInPhoneReceiver() {
        mComeInPhoneReceiver = ComeInPhoneReceiver()
        IntentFilter().apply {
            priority = Int.MAX_VALUE
            addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED)
            registerReceiver(mComeInPhoneReceiver, this)
        }
    }

    private fun initViews() {
        mVp_alm = findViewById(R.id.vp_alm)
        val mSvp_alm: StandardGSYVideoPlayer = findViewById(R.id.svp_alm)
        mLocalMusicPresenter.setVideoPlayer(mSvp_alm)
        val rv = mVp_alm.getChildAt(0)
        if (rv is RecyclerView) {
            rv.overScrollMode = OVER_SCROLL_NEVER
        }
        mVp_alm.orientation = ORIENTATION_HORIZONTAL
        mVp_alm.offscreenPageLimit = 1
        mVp_alm_adapter = object : FragmentStateAdapter(this) {
            override fun getItemCount(): Int {
                return mVp_alm_adapter_fragments.size
            }

            override fun createFragment(position: Int): Fragment {
                return mVp_alm_adapter_fragments.get(position)
            }
        }
        mVp_alm.adapter = mVp_alm_adapter
        mBackDialog = CommonDialog.Builder()
            .setContext(this)
            .setLayoutId(R.layout.dialog_back)
            .setLeftViewId(R.id.negative)
            .setRightViewId(R.id.positive)
            .setCancelable(false)
            .setDefaultListener(object : CommonDialog.CommonDialogDefaultOnClickListener {
                override fun onLeftViewClick(dialog: Dialog?) {
                    dialog?.dismiss()
                    onResumePlay()
                }

                override fun onCommonViewClick(dialog: Dialog?) {

                }

                override fun onRightViewClick(dialog: Dialog?) {
                    dialog?.dismiss()
                    val intent = Intent(this@LocalMusicActivity, SplashActivity::class.java)
                    intent.putExtra("mBack",true)
                    startActivity(intent)
                    finish()
                }

            }).build()
        mScaningDialog = CommonDialog.Builder()
            .setContext(this)
            .setLayoutId(R.layout.dialog_scan_local)
            .setLeftViewId(R.id.tv_dsl_cancel)
            .setCancelable(false)
            .setDefaultListener(object : CommonDialog.CommonDialogDefaultOnClickListener {
                override fun onLeftViewClick(dialog: Dialog?) {
                    findMusicFragment().mLoadLocalMusicJob?.cancel()
                    findMusicFragment().reset()
                    dialog?.dismiss()
                }

                override fun onCommonViewClick(dialog: Dialog?) {

                }

                override fun onRightViewClick(dialog: Dialog?) {

                }

            }).build()
    }

    private fun generateRemoteViews() {
        mRemoteView = RemoteViews(packageName, R.layout.notification_play_control)
        var prePendingIntent = PendingIntent.getBroadcast(
            applicationContext, 0, Intent(NotificationPlayStatus.STATUS_PREV),
            PendingIntent.FLAG_IMMUTABLE
        )
        var playPendingIntent = PendingIntent.getBroadcast(
            applicationContext, 0, Intent(NotificationPlayStatus.STATUS_PLAY_OR_PAUSE),
            PendingIntent.FLAG_IMMUTABLE
        )
        var nextPendingIntent = PendingIntent.getBroadcast(
            applicationContext, 0, Intent(NotificationPlayStatus.STATUS_NEXT),
            PendingIntent.FLAG_IMMUTABLE
        )
        var closePendingIntent = PendingIntent.getBroadcast(
            applicationContext, 0, Intent(NotificationPlayStatus.STATUS_CLOSE),
            PendingIntent.FLAG_IMMUTABLE
        )
        mRemoteView?.apply {
            setOnClickPendingIntent(R.id.iv_npc_pre, prePendingIntent)
            setOnClickPendingIntent(R.id.iv_npc_playorpause, playPendingIntent)
            setOnClickPendingIntent(R.id.iv_npc_next, nextPendingIntent)
            setOnClickPendingIntent(R.id.iv_npc_close, closePendingIntent)
        }
    }

    fun showNoMusicFromLrcToast() {
        showToast(mLocalMusicPresenter.getNoMusicFromLrcInfo())
    }

    fun showNoMusicFromMusicToast(permission: Boolean) {
        showToast(mLocalMusicPresenter.getNoMusicFromMusicInfo(permission))
    }

    fun onProgress(currentProgress: Int, duration: Int) {
        findMusicFragment().autoSyncMusicProgress(currentProgress, duration)
        findLrcFragment().autoSyncLrcProgress(
            currentProgress,
            duration,
            mLocalMusicPresenter.mCurrentLocalMusicPath
        )
    }

    fun onSeletedMusic(): Boolean {
        return findMusicFragment().mCurrentItemSelectedPosition != -1
    }

    fun onMediaPlayerPrepared() {
        showNotification()
        findMusicFragment().onMediaPlayerPrepared()
        findLrcFragment().onMediaPlayerPrepared()
        updateNotification(true)
    }

    fun changeLfStartOrPause(show: Boolean) {
        findLrcFragment().showStartOrPause(show)
    }

    fun changeMfStartOrPause() {
        findMusicFragment().onPlayOrPauseClick()
    }

    fun startPrepareMusic(lm: LocalMusic) {
        mLocalMusicPresenter.prepareMusicAsync(lm)
    }

    fun autoChangeNextSong() {
        findMusicFragment().autoChangeNextSong()
    }

    fun handChangeNextSong(next: Boolean) {
        findMusicFragment().handChangeNextSong(next)
    }

    fun showExitDialog() {
        mBackDialog.show()
        onPausePlay()
    }

    fun handSyncProgress(currentProgress: Int) {
        mLocalMusicPresenter.seekTo(currentProgress)
    }

    fun showScanlingDialogSize(size: Int) {
        if (!mScaningDialog.isShowing) {
            mScaningDialog.show()
        }
        mScaningDialog.findViewById<TextView>(R.id.tv_dsl_scaned).text = "已扫描到${size}首歌曲"
    }

    fun dismissScanlingDialog() {
        mScaningDialog.dismiss()
    }

    fun resetUI() {
        findMusicFragment().refreshAlbumImg(false, null)
        findLrcFragment().setNoLrcs()
        mRemoteView?.setImageViewResource(R.id.iv_npc_album, R.drawable.app_notification_logo)
        mNotificationManager?.notify(mNotificationId, mNotification)
    }

    fun refreshAlbumImg(bitmap: Bitmap?) {
        findMusicFragment().refreshAlbumImg(true, bitmap)
        bitmap?.let { mRemoteView?.setImageViewBitmap(R.id.iv_npc_album, it) }
        mNotificationManager?.notify(mNotificationId, mNotification)
    }

    fun showToast(info: String) {
        Toast.makeText(applicationContext, info, Toast.LENGTH_SHORT).show()
    }

    fun showFilterFailToast() {
        showToast(mLocalMusicPresenter.getFilterFailInfo())
    }

    fun moveToMusicFragment() {
        mVp_alm.currentItem = 0
    }

    fun sendProgress() {
        mLocalMusicPresenter.sendProgress()
    }

    fun onError() {
        findMusicFragment().onError()
        findLrcFragment().onError()
    }

    fun isPlaying(): Boolean {
        return mLocalMusicPresenter.isPlaying()
    }

    fun play(){
        mLocalMusicPresenter.play()
    }

    fun pause(){
        mLocalMusicPresenter.pause()
    }
    inner class ComeInPhoneReceiver : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            var manager = context.getSystemService(TELEPHONY_SERVICE) as TelephonyManager
            val callState = manager.callState
            if (callState == TelephonyManager.CALL_STATE_RINGING) {
                mIsRingLing = true
                onStop()
            } else if (callState == TelephonyManager.CALL_STATE_IDLE) {
                mIsRingLing = false
                onResume()
            }
        }
    }

    inner class NotificationActionReceiver : BroadcastReceiver() {
        override fun onReceive(p0: Context?, i: Intent) {
            dealAction(i.action)
        }

        private fun dealAction(action: String?) {
            action?.let {
                when (it) {
                    NotificationPlayStatus.STATUS_PREV -> {
                        handChangeNextSong(false)
                    }

                    NotificationPlayStatus.STATUS_PLAY_OR_PAUSE -> {
                        changeMfStartOrPause()
                    }

                    NotificationPlayStatus.STATUS_NEXT -> {
                        handChangeNextSong(true)
                    }

                    NotificationPlayStatus.STATUS_CLOSE -> {
                        dismissNotification()
                    }

                    else -> {

                    }
                }
            }
        }
    }
}